

package cn.iocoder.yudao.module.apijson.framework;

import apijson.*;
import apijson.orm.*;
import apijson.orm.JSONRequest;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.common.biz.system.roleaccess.RoleAccessCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.roleaccess.dto.RoleAccessDTO;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.rmi.ServerException;
import java.util.*;

import static apijson.JSON.*;
import static apijson.JSONMap.KEY_ORDER;
import static apijson.JSONMap.isTableKey;
import static apijson.JSONRequest.KEY_COUNT;
import static apijson.orm.AbstractSQLConfig.KEY_DELETED_KEY;
import static apijson.orm.AbstractSQLConfig.KEY_DELETED_VALUE;
import static cn.iocoder.yudao.module.apijson.framework.APIJSONConstant.*;


/**
 * 权限验证器
 *
 * @author Lemon
 */
@Slf4j
public class APIJSONVerifier extends AbstractVerifier<Long, JSONObject, JSONArray> {
    public static final String TAG = "APIJSONVerifier";
    public static boolean ENABLE_APIJSON_ROUTER = false;
    public static Map<String, SortedMap<Integer, Map<String, Object>>> DOCUMENT_MAP;

    static {
        DOCUMENT_MAP = new HashMap<>();
        ACCESS_FAKE_DELETE_MAP=new HashMap<>();
    }
    //=================================================initAccess======================================================

    /**
     * 初始化，加载所有权限配置
     */
    public static JSONObject initAccess(boolean shutdownWhenServerError) throws ServerException {
        return initAccess(shutdownWhenServerError, null);
    }

    /**
     * 初始化，加载所有权限配置
     */
    public static JSONObject initAccess(
            boolean shutdownWhenServerError, APIJSONCreator creator) throws ServerException {
        return initAccess(shutdownWhenServerError, creator, null);
    }

    /**
     * 初始化，加载所有权限配置
     *
     * @param table 表内自定义数据过滤条件
     */
    public static JSONObject initAccess(
            boolean shutdownWhenServerError, APIJSONCreator creator, JSONObject table) throws ServerException {
        if (creator == null) {
            creator = APIJSONApplication.DEFAULT_APIJSON_CREATOR;
        }
        boolean isAll = table == null || table.isEmpty();
        JSONObject access = isAll ? JSON.createJSONObject() : table;
        if (!Log.DEBUG) {
            access.put(APIJSONConstant.KEY_DEBUG, 0);
        }
        JSONObject accessItem = JSON.createJSONObject();
        accessItem.put(ACCESS_, access);
        accessItem.put(KEY_COUNT, 0);

        JSONObject request = JSON.createJSONObject();
        request.put(ACCESS_ + "[]", accessItem);

        JSONObject response = creator.createParser().setMethod(RequestMethod.GET).setNeedVerify(false).parseResponse(request);
        if (!JSONResponse.isSuccess(response)) {
            log.error("initAccess 获取权限配置异常！");
            onServerError("查询权限配置异常 !", shutdownWhenServerError);
        }

        JSONArray list = getJSONArray(response, ACCESS_ + "[]");
        if ((isAll && list == null) || list.isEmpty()) {
            log.warn("initAccess isAll && size <= 0，，没有可用的权限配置");
            return response;
        }
        log.debug("initAccess < for size = {} >>>>>>>>>>>>>>>>>>>>>>>", list.size());
        //表名映射
        Map<String, String> newTKMap = new LinkedHashMap<>();
        //数据库名/模式
        Map<String, String> tableSchemaMap = new LinkedHashMap<>();
        //逻辑删除
        Map<String, Map<String, Object>> newFakeDeleteMap = new LinkedHashMap<>();

        for (Object o : list) {
            JSONObject item = (JSONObject) o;
            newTKMap.put(item.getString("alias"), item.getString("name"));
            tableSchemaMap.put(item.getString("alias"), item.getString("schema"));
            //逻辑删除
            JSONObject delMap = new JSONObject();
            delMap.put(KEY_DELETED_KEY, "deleted");
            delMap.put(KEY_DELETED_VALUE, 1);
            newFakeDeleteMap.put(item.getString("alias"), delMap);
        }
        if (isAll) {  // 全量更新
            APIJSONSQLConfig.TABLE_KEY_MAP = newTKMap;
            ACCESS_FAKE_DELETE_MAP=newFakeDeleteMap;
        } else {
            APIJSONSQLConfig.TABLE_KEY_MAP.putAll(newTKMap);
            ACCESS_FAKE_DELETE_MAP.putAll(newFakeDeleteMap);

        }
        APIJSONSQLConfig.TABLE_SCHEMA_MAP = tableSchemaMap;
        log.info("initAccess  for < ACCESS_MAP.size() = {}", ACCESS_MAP.size());
        return response;
    }

    //=================================================initRequest======================================================

    /**
     * 初始化，加载所有请求校验配置
     */
    public static JSONObject initRequest(boolean shutdownWhenServerError) throws ServerException {
        return initRequest(shutdownWhenServerError, null);
    }

    /**
     * 初始化，加载所有请求校验配置
     */
    public static JSONObject initRequest(
            boolean shutdownWhenServerError, APIJSONCreator creator) throws ServerException {
        return initRequest(shutdownWhenServerError, creator, null);
    }

    /**
     * 初始化，加载所有请求校验配置
     *
     * @param table 表内自定义数据过滤条件
     */
    public static JSONObject initRequest(
            boolean shutdownWhenServerError, APIJSONCreator creator, JSONObject table) throws ServerException {
        if (creator == null) {
            creator = APIJSONApplication.DEFAULT_APIJSON_CREATOR;
        }

        boolean isAll = table == null || table.isEmpty();
        JSONObject tblObj = createJSONObject();
        tblObj.put(KEY_ORDER, "version-,id+");
        JSONObject requestTable = isAll ? tblObj : table;
        if (!Log.DEBUG) {
            requestTable.put(APIJSONConstant.KEY_DEBUG, 0);
        }

        JSONObject requestItem = JSON.createJSONObject();
        requestItem.put(REQUEST_, requestTable);  // 方便查找
        requestItem.put(KEY_COUNT, 0);

        JSONObject request = JSON.createJSONObject();
        request.put(REQUEST_ + "[]", requestItem);

        JSONObject response = creator.createParser().setMethod(RequestMethod.GET).setNeedVerify(false).parseResponse(request);
        if (!JSONResponse.isSuccess(response)) {
            Log.e(TAG, "\n\n\n\n\n !!!! 查询请求校验规则配置异常 !!!\n" + getString(response, JSONResponse.KEY_MSG) + "\n\n\n\n\n");
            onServerError("查询请求校验规则配置异常 !", shutdownWhenServerError);
        }

        JSONArray list = getJSONArray(response, REQUEST_ + "[]");
        int size = list == null ? 0 : list.size();
        if (isAll && size == 0) {
            Log.w(TAG, "initRequest isAll && size <= 0，没有可用的请求校验规则配置");
            return response;
        }

        Log.d(TAG, "initRequest < for REQUEST_MAP.size() = " + REQUEST_MAP.size() + " <<<<<<<<<<<<<<<<<<<<<<<<");

        Map<String, SortedMap<Integer, Map<String, Object>>> newMap = new LinkedHashMap<>();

        for (int i = 0; i < size; i++) {
            JSONObject item = getJSONObject(list, i);
            if (item == null) {
                continue;
            }

            String version = getString(item, "version");
            if (StringUtil.isEmpty(version, true)) {
                Log.e(TAG, "initRequest  for  StringUtil.isEmpty(version, true)，Request 表中的 version 不能为空！");
                onServerError("服务器内部错误，Request 表中的 version 不能为空！", shutdownWhenServerError);
            }

            String method = getString(item, "method");
            if (StringUtil.isEmpty(method, true)) {
                Log.e(TAG, "initRequest  for  StringUtil.isEmpty(method, true)，Request 表中的 method 不能为空！");
                onServerError("服务器内部错误，Request 表中的 method 不能为空！", shutdownWhenServerError);
            }

            String tag = getString(item, "tag");
            if (StringUtil.isEmpty(tag, true)) {
                Log.e(TAG, "initRequest  for  StringUtil.isEmpty(tag, true)，Request 表中的 tag 不能为空！");
                onServerError("服务器内部错误，Request 表中的 tag 不能为空！", shutdownWhenServerError);
            }

            JSONObject structure = JSON.parseObject(getString(item, "structure"));

            JSONObject target = null;

            if (structure != null) {
                target = structure;
                if (!structure.containsKey(tag)) { //tag 是 Table 名或 Table[]

                    boolean isArrayKey = tag.endsWith(":[]");  //  apijson.isArrayKey(tag);
                    String key = isArrayKey ? tag.substring(0, tag.length() - 3) : tag;

                    if (isTableKey(key)) {
                        if (isArrayKey) { //自动为 tag = Comment:[] 的 { ... } 新增键值对 "Comment[]":[] 为 { "Comment[]":[], ... }
                            target.put(key + "[]", JSON.createJSONArray());
                        } else { //自动为 tag = Comment 的 { ... } 包一层为 { "Comment": { ... } }
                            target = JSON.createJSONObject();
                            target.put(tag, structure);
                        }
                    }
                }
            }

            if (target == null || target.isEmpty()) {
                Log.e(TAG, "initRequest  for  target == null || target.isEmpty()");
                onServerError("服务器内部错误，Request 表中的 version = " + version + ", method = " + method + ", tag = " + tag + " 对应的 structure 不能为空！", shutdownWhenServerError);
            }

            String cacheKey = getCacheKeyForRequest(method, tag);
            SortedMap<Integer, Map<String, Object>> versionedMap = newMap.get(cacheKey);
            if (versionedMap == null) {
                versionedMap = new TreeMap<>(new Comparator<Integer>() {

                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o2 == null ? -1 : o2.compareTo(o1);  // 降序
                    }
                });
            }
            versionedMap.put(Integer.valueOf(version), item);
            newMap.put(cacheKey, versionedMap);
        }

        if (isAll) {  // 全量更新
            REQUEST_MAP = new LinkedHashMap<>();
            REQUEST_MAP.putAll(newMap);
        } else {
            REQUEST_MAP.putAll(newMap);
        }

        Log.d(TAG, "initRequest  for /> REQUEST_MAP.size() = " + REQUEST_MAP.size() + " >>>>>>>>>>>>>>>>>>>>>>>");

        return response;
    }
    //=================================================initDocument====================================================

    /**
     * 初始化，加载所有请求校验配置
     */
    public static JSONObject initDocument(
            boolean shutdownWhenServerError, APIJSONCreator creator) throws ServerException {
        return initDocument(shutdownWhenServerError, creator, null);
    }

    /**
     * 初始化，加载所有请求校验配置
     *
     * @param table 表内自定义数据过滤条件
     */
    public static JSONObject initDocument(
            boolean shutdownWhenServerError, APIJSONCreator creator, JSONObject table) throws ServerException {
        if (creator == null) {
            creator = APIJSONApplication.DEFAULT_APIJSON_CREATOR;
        }

        boolean isAll = table == null || table.isEmpty();
        JSONObject document = isAll ? JSON.createJSONObject(new JSONRequest("apijson{}", "length(apijson)>0").setOrder("version-,id+")) : table;
        if (!Log.DEBUG) {
            document.put(APIJSONConstant.KEY_DEBUG, 0);
        }

        JSONObject requestItem = JSON.createJSONObject();
        requestItem.put(DOCUMENT_, document);  // 方便查找
        requestItem.put(KEY_COUNT, 0);

        JSONObject request = JSON.createJSONObject();
        request.put(DOCUMENT_ + "[]", requestItem);

        JSONObject response = creator.createParser().setMethod(RequestMethod.GET).setNeedVerify(false).parseResponse(request);
        if (!JSONResponse.isSuccess(response)) {
            Log.e(TAG, "\n\n\n\n\n !!!! 查询请求映射配置异常 !!!\n" + getString(response, JSONResponse.KEY_MSG) + "\n\n\n\n\n");
            onServerError("查询请求映射配置异常 !", shutdownWhenServerError);
        }

        JSONArray list = getJSONArray(response, DOCUMENT_ + "[]");
        int size = list == null ? 0 : list.size();
        if (isAll && size == 0) {
            Log.w(TAG, "initDocument isAll && size <= 0，没有可用的请求映射配置");
            return response;
        }

        Log.d(TAG, "initDocument < for DOCUMENT_MAP.size() = " + DOCUMENT_MAP.size() + " <<<<<<<<<<<<<<<<<<<<<<<<");


        Map<String, SortedMap<Integer, Map<String, Object>>> newMap = new LinkedHashMap<>();

        for (int i = 0; i < size; i++) {
            JSONObject item = getJSONObject(list, i);
            if (item == null) {
                continue;
            }

            String version = getString(item, "version");
            if (StringUtil.isEmpty(version, true)) {
                onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name")
                        + " 对应 version 不能为空！", shutdownWhenServerError);
            }

            String url = getString(item, "url");
            int index = url == null ? -1 : url.indexOf("/");
            if (index != 0) {
                onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                        + " 对应 url 值错误，必须以 / 开头！", shutdownWhenServerError);
            }

            String requestStr = getString(item, "request");

            String apijson = getString(item, "apijson");
            if (StringUtil.isEmpty(apijson)) {
                if (!StringUtil.isBranchUrl(url)) {
                    onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                            + " 对应 url 值错误！只允许合法的 URL 格式！", shutdownWhenServerError);
                }
            } else {
                if (StringUtil.isNotEmpty(requestStr)) {
                    try {
                        JSON.parseObject(requestStr);
                    } catch (Exception e) {
                        onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                                + " 对应 request 值 " + requestStr + " 错误！只允许合法的 M 格式！" + e.getMessage(), shutdownWhenServerError);
                    }
                }

                try {
                    JSON.parseObject(apijson);
                } catch (Exception e) {
                    onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                            + " 对应 apijson 值 " + apijson + " 错误！只允许合法的 M 格式！" + e.getMessage(), shutdownWhenServerError);
                }

                if (url != null) {
                    index = url.lastIndexOf("/");
                }
                String method = index < 0 ? null : url.substring(0, index);
                String tag = index < 0 ? null : url.substring(index + 1);

                index = method == null ? -1 : method.lastIndexOf("/");
                method = index < 0 ? method : method.substring(index + 1);

                if (!METHODS.contains(method)) {
                    onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                            + " 对应路径 /{method}/{tag} 中 method 值 " + method + " 错误！apijson 字段不为空时只允许 " + METHODS + " 中的一个！", shutdownWhenServerError);
                }

                if (!StringUtil.isName(tag)) {
                    onServerError("服务器内部错误，Document 表中的 id=" + getString(item, "id") + ", name=" + getString(item, "name") + ", url=" + url
                            + " 对应路径 /{method}/{tag} 中 tag 值 " + tag + " 错误！apijson 字段不为空时只允许变量命名格式！", shutdownWhenServerError);
                }

                String cacheKey = getCacheKeyForRequest(method, tag);
                SortedMap<Integer, Map<String, Object>> versionedMap = newMap.get(cacheKey);
                if (versionedMap == null) {
                    versionedMap = new TreeMap<>(new Comparator<Integer>() {

                        @Override
                        public int compare(Integer o1, Integer o2) {
                            return o2 == null ? -1 : o2.compareTo(o1);  // 降序
                        }
                    });
                }
                versionedMap.put(Integer.valueOf(version), item);
                newMap.put(cacheKey, versionedMap);
            }

        }

        if (isAll) {  // 全量更新
            DOCUMENT_MAP = newMap;
        } else {
            DOCUMENT_MAP.putAll(newMap);
        }

        Log.d(TAG, "initDocument  for /> DOCUMENT_MAP.size() = " + DOCUMENT_MAP.size() + " >>>>>>>>>>>>>>>>>>>>>>>");

        return response;
    }
    //==================================================================================================================

    private static final String USER_ID = "user_id";
    private static final String DEPT_ID = "dept_id";
    private static final String SUPER_ADMIN = "super_admin";
    static final String requestConfig = "{\"Comment\":{\"REFUSE\": \"id\", \"MUST\": \"userId,momentId,content\"}, \"INSERT\":{\"@role\":\"OWNER\"}}";
    static final String responseConfig = "{\"User\":{\"REMOVE\": \"phone\", \"REPLACE\":{\"sex\":2}, \"INSERT\":{\"name\":\"api\"}, \"UPDATE\":{\"verifyURLList-()\":\"verifyURLList(pictureList)\"}}}";

    /**
     * 测试 Request 和 Response 的数据结构校验
     */
    public static void testStructure() throws Exception {
        Parser<Long, JSONObject, JSONArray> parser = APIJSONApplication.createParser();

        JSONObject request;
        try {
            request = JSON.parseObject("{\"Comment\":{\"userId\":0}}");
            Log.d(TAG, "test  verifyRequest = " + AbstractVerifier.verifyRequest(RequestMethod.POST, "", JSON.parseObject(requestConfig), request, parser));
        } catch (Throwable e) {
            if (!(e instanceof IllegalArgumentException) || !"POST请求，Comment 里面不能缺少 momentId 等[userId,momentId,content]内的任何字段！".equals(e.getMessage())) {
                throw e;
            }
            Log.d(TAG, "测试 Operation.MUST 校验缺少字段：成功");
        }
        try {
            request = JSON.parseObject("{\"Comment\":{\"id\":0, \"userId\":0, \"momentId\":0, \"content\":\"apijson\"}}");
            Log.d(TAG, "test  verifyRequest = " + AbstractVerifier.verifyRequest(RequestMethod.POST, "", JSON.parseObject(requestConfig), request, parser));
        } catch (Throwable e) {
            if (!(e instanceof IllegalArgumentException) || !"POST请求，/Comment 不能传 id ！".equals(e.getMessage())) {
                throw e;
            }
            Log.d(TAG, "测试 Operation.REFUSE 校验不允许传字段：成功");
        }
        request = JSON.parseObject("{\"Comment\":{\"userId\":0, \"momentId\":0, \"content\":\"apijson\"}}");
        Log.d(TAG, "test  verifyRequest = " + AbstractVerifier.verifyRequest(RequestMethod.POST, "", JSON.parseObject(requestConfig), request, parser));
        AssertUtil.assertEqual("OWNER", getString(request, "@role"));
        Log.d(TAG, "测试 Operation.INSERT 不存在字段时插入：成功");


        JSONObject response;
        response = JSON.parseObject("{\"User\":{\"userId\":0}}");
        Log.d(TAG, "test  verifyResponse = " + AbstractVerifier.verifyResponse(RequestMethod.GET, "", JSON.parseObject(responseConfig), response, parser, null));
        AssertUtil.assertEqual("verifyURLList(pictureList)", getJSONObject(response, "User").get("verifyURLList-()"));
        Log.d(TAG, "测试 Operation.UPDATE 强制插入/替换：成功");
        //=======
        response = JSON.parseObject("{\"User\":{\"userId\":0, \"phone\":\"12345678\"}}");
        Log.d(TAG, "test  verifyResponse = " + AbstractVerifier.verifyResponse(RequestMethod.GET, "", JSON.parseObject(responseConfig), response, parser, null));
        AssertUtil.assertEqual(null, getJSONObject(response, "User").get("phone"));
        Log.d(TAG, "测试 Operation.REMOVE 强制移除：成功");
        //=======
        response = JSON.parseObject("{\"User\":{\"userId\":0, \"phone\":\"12345678\", \"sex\":1}}");
        Log.d(TAG, "test  verifyResponse = " + AbstractVerifier.verifyResponse(RequestMethod.GET, "", JSON.parseObject(responseConfig), response, parser, null));
        AssertUtil.assertEqual("api", getJSONObject(response, "User").get("name"));
        Log.d(TAG, "测试 Operation.INSERT 不存在字段时插入：成功");
        //=======
        response = JSON.parseObject("{\"User\":{\"id\":0, \"name\":\"tommy\", \"phone\":\"12345678\", \"sex\":1}}");
        Log.d(TAG, "test  verifyResponse = " + AbstractVerifier.verifyResponse(RequestMethod.GET, "", JSON.parseObject(responseConfig), response, parser, null));
        AssertUtil.assertEqual(2, getJSONObject(response, "User").get("sex"));
        Log.d(TAG, "测试 Operation.REPLACE 存在字段时替换：成功");

    }


    protected static void onServerError(String msg, boolean shutdown) throws ServerException {
        Log.e(TAG, "\n校验配置测试未通过！\n请修改 Access/Request 表里的记录！\n保证所有配置都是正确的！！！\n\n原因：\n" + msg);

        if (shutdown) {
            System.exit(1);
        } else {
            throw new ServerException(msg);
        }
    }

    protected Parser<Long, JSONObject, JSONArray> parser;

    @Override
    public Parser<Long, JSONObject, JSONArray> getParser() {
        if (parser == null) {
            parser = createParser();
        }
        return parser;
    }

    @Override
    public APIJSONVerifier setParser(AbstractParser<Long, JSONObject, JSONArray> parser) {
        this.parser = parser;
        return this;
    }

    @NotNull
    @Override
    public APIJSONParser createParser() {
        APIJSONParser parser = APIJSONApplication.createParser();
        parser.setVisitor(visitor);
        return parser;
    }
    //=================================================================================================================

    /**
     * 验证权限是否通过
     */
    @Override
    public boolean verifyAccess(SQLConfig<Long, JSONObject, JSONArray> config) throws Exception {
        if (!ENABLE_VERIFY_ROLE) {
            throw new UnsupportedOperationException("AbstractVerifier.ENABLE_VERIFY_ROLE == false " +
                    "时不支持校验角色权限！如需支持则设置 AbstractVerifier.ENABLE_VERIFY_ROLE = true ！");
        }
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        verifyUserAccess(config, loginUserId); //检测用户是否有表的方法使用权
        verifyUserDataAuth(config, loginUserId); //验证使用的角色
        return true;
    }

    /**
     * 允许请求使用的所以可能角色
     */
    public void verifyUserAccess(SQLConfig<Long, JSONObject, JSONArray> config, Long loginUserId) throws Exception {
        //判断是否有权限
        String table = config.getTable();
        RequestMethod method = config.getMethod();
        if (!verifyUserAccessSub(table, method, loginUserId)) {
            throw new ServerException(StrUtil.format("用户没有权限访问 {} {}", table, method));
        }
    }

    /**
     * 检测用户是否有表的方法使用权
     */
    private boolean verifyUserAccessSub(String table, RequestMethod method, Long loginUserId) {
        PermissionCommonApi permissionCommonApi = SpringUtils.getApplicationContext().getBean(PermissionCommonApi.class);
        if (permissionCommonApi.hasAnyRoles(loginUserId, SUPER_ADMIN)) {
            return true;
        }
        RoleAccessCommonApi bean = SpringUtils.getApplicationContext().getBean(RoleAccessCommonApi.class);
        List<RoleAccessDTO> roleAccessDTOS = bean.getRoleAccessListByUserId(SecurityFrameworkUtils.getLoginUserId());
        if (roleAccessDTOS == null) {
            return false;
        }
        for (RoleAccessDTO roleAccessDTO : roleAccessDTOS) {
            if (!table.equals(roleAccessDTO.getAlias())) {
                continue;
            }
            if (roleAccessDTO.getMethod().equals(method.name())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 验证用户数据权限
     */
    public void verifyUserDataAuth(SQLConfig<Long, JSONObject, JSONArray> config, Long loginUserId) throws Exception {
        //获取访问者的数据权限
        Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
        PermissionCommonApi bean = SpringUtils.getApplicationContext().getBean(PermissionCommonApi.class);
        DeptDataPermissionRespDTO permission = bean.getDeptDataPermissionAPIJSONRedis(loginUserId);
        //post 请求
        if (config.getMethod() == RequestMethod.POST) {
            post(config, loginUserId, loginUserDeptId);
            return;
        }
        //全部权限
        if (permission.getAll()) {
            return;
        }
        //个人权限
        if (permission.getSelf()) {
            Object requestId = config.getWhere(USER_ID, true);
            if (requestId != null && !StringUtil.get(requestId).equals(StringUtil.get(loginUserId))) {
                throw new IllegalAccessException("参数请求错误");
            }
            config.putWhere(USER_ID, loginUserId, true);
            return;
        }
        //部门权限
        Set<Long> deptIds = permission.getDeptIds();
        if (deptIds != null && !deptIds.isEmpty()) {
            config.putWhere(DEPT_ID + "{}", deptIds, true);
            return;
        }
        throw new ServerException("用户没有权限访问");
    }

    /**
     * post 请求权限
     */
    private void post(SQLConfig<Long, JSONObject, JSONArray> config, Long loginUserId, Long loginDeptId) throws IllegalAccessException {
        List<String> c = config.getColumn();
        List<List<Object>> ovs = config.getValues();
        if ((c == null || c.isEmpty()) || (ovs == null || ovs.isEmpty())) {
            throw new IllegalArgumentException("POST 请求必须在Table内设置要保存的 key:value ！");
        }
        int index = c.indexOf(USER_ID);
        int deptIndex = c.indexOf(DEPT_ID);
        if (deptIndex >= 0 || index >= 0) {
            throw new IllegalAccessException("请求参数错误");
        }

        List<String> nc = new ArrayList<>(c);
        nc.add(USER_ID);
        nc.add(DEPT_ID);
        config.setColumn(nc);
        List<List<Object>> nvs = new ArrayList<>();
        List<Object> nvl;
        for (List<Object> ovl : ovs) {
            nvl = ovl == null || ovl.isEmpty() ? new ArrayList<>() : new ArrayList<>(ovl);
            nvl.add(loginUserId);
            nvl.add(loginDeptId);
            nvs.add(nvl);
        }
        config.setValues(nvs);
    }
}
